package com.payment.utils.payment;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.payment.utils.HMACSHA256;
import com.payment.utils.MD5;
import com.payment.utils.Md5Encrypt;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.regex.Pattern;

public class WeiXinPayUtil {
    /**
     * @2016年12月14日下午3:47:29
     * @function：动态生成二维码图片，并直接以流的形式输出到页面
     * @author ：lj
     */
    public void getQRCode(HttpServletRequest request,HttpServletResponse response) throws Exception{
        String code_url=request.getParameter("code_url");
        MultiFormatWriter multi=new MultiFormatWriter();
        Map map=new HashMap();
        map.put(EncodeHintType.CHARACTER_SET, "UTF-8");//设置字符集编码类型
        BitMatrix bitMatrix=null;
        try {
            bitMatrix=multi.encode(code_url, BarcodeFormat.QR_CODE, 300, 300,map);
            BufferedImage image=toBufferedImage(bitMatrix);
            //输出二维码图片流
            try {
                ImageIO.write(image, "png", response.getOutputStream());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (WriterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public BufferedImage toBufferedImage(BitMatrix matrix){
        int WHITE=0xFFFFFFFF;
        int BLACK=0xFF000000;
        int width=matrix.getWidth();
        int height=matrix.getHeight();
        BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for(int x=0;x<width;x++){
            for(int y=0;y<height;y++){
                image.setRGB(x, y, matrix.get(x,y) ? BLACK : WHITE);
            }
        }
        return image;
    }
    /**
     * 获取32位随机字符串
     *
     * @return
     */
    public static String getNonceStr() {
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        Random rd = new Random();
        for (int i = 0; i < 32; i++) {
            sb.append(str.charAt(rd.nextInt(str.length())));
        }
        return sb.toString();
    }

    /**
     * 插入XML标签
     *
     * @param sb
     * @param Key
     * @param value
     * @return
     */
    public static StringBuilder setXmlKV(StringBuilder sb, String Key,
                                         String value) {
        sb.append("<");
        sb.append(Key);
        sb.append(">");

        sb.append(value);

        sb.append("</");
        sb.append(Key);
        sb.append(">");

        return sb;
    }

    /**
     * 解析XML 获得名称为para的参数值
     *
     * @param xml
     * @param para
     * @return
     */
    public static String getXmlPara(String xml, String para) {
        int start = xml.indexOf("<" + para + ">");
        int end = xml.indexOf("</" + para + ">");

        if (start < 0 && end < 0) {
            return null;
        }
        return xml.substring(start + ("<" + para + ">").length(), end)
                .replace("<![CDATA[", "").replace("]]>", "");
    }

    /**
     * 获取ip地址
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        InetAddress addr = null;
        try {
            addr = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            return request.getRemoteAddr();
        }
        byte[] ipAddr = addr.getAddress();
        String ipAddrStr = "";
        for (int i = 0; i < ipAddr.length; i++) {
            if (i > 0) {
                ipAddrStr += ".";
            }
            ipAddrStr += ipAddr[i] & 0xFF;
        }
        return ipAddrStr;
    }
    /*
     * 方法二：推荐，速度最快 判断是否为整数
     *
     * @param str 传入的字符串
     *
     * @return 是整数返回true,否则返回false
     * Pattern.compile("^[-\\+]?[\\d]*$")不要在方法体内直接实现
     */
    private static Pattern NUMBER_PATTERN = Pattern.compile("^[-\\+]?[\\d]*$");

    public static boolean isInteger(String str) {
        Pattern pattern = NUMBER_PATTERN;
        return pattern.matcher(str).matches();
    }

    /***
     * 用于获取用户真实ip的方法
     * @param request
     * @return
     */
    public static String getIp2(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }


    /***
     * 微信H5支付统一下单
     * @param payId
     * @param totel_fee
     * @param appId
     * @param mchId
     * @param body
     * @param sceneInfo
     * @param key
     * @param ipAddrStr
     * @return
     * @throws Exception
     */
    public static String UnifiedOrderH5(String payId, Integer totel_fee, String appId, String mchId, String body, String sceneInfo, String key, String ipAddrStr) throws Exception{
        // 设置访问路径
        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // 随机
        String nonce_str = getNonceStr().toUpperCase();
        // 组装请求参数,按照ASCII排序
        String unifiedOrdersign =
                "appid=" +appId+
                        "&body=" + body +
                        "&mch_id=" + mchId +
                        "&nonce_str=" + nonce_str +
                        "&notify_url=" + WxPayConstants.NOTIFY_URL +
                        "&out_trade_no=" + payId +
                        "&scene_info=" + sceneInfo +
                        "&spbill_create_ip=" + ipAddrStr +
                        "&total_fee=" + totel_fee.toString() +
                        "&trade_type=" + WxPayConstants.TRADE_TYPE_H5 +
                        "&key=" +key ;
        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
        System.out.println("H5统一下单参与签名的字符串是：" + unifiedOrdersign);
        String sign = MD5.calcMD5(unifiedOrdersign).toUpperCase();
        String sign1 = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, key).toUpperCase();
        System.out.println("H5下单MD5值:" + sign+";H5下单Md5Encrypt值:"+sign1+";H5下单HMACSHA256值:"+sign2);

        // 组装包含openid用于请求统一下单返回结果的XML
        StringBuilder sb = new StringBuilder("");
        sb.append("<xml>");
        setXmlKV(sb, "appid", appId);
        setXmlKV(sb, "body", body);
        setXmlKV(sb, "mch_id", mchId);
        setXmlKV(sb, "nonce_str", nonce_str);
        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_URL);
        setXmlKV(sb, "out_trade_no", payId);
        setXmlKV(sb, "scene_info", sceneInfo);
        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
        setXmlKV(sb, "total_fee", totel_fee.toString());
        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_H5);
        setXmlKV(sb, "sign", sign);
        sb.append("</xml>");
        System.out.println("H5统一下单请求：" + sb);
        // 这个处理是为了防止传中文的时候出现签名错误
        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
        httppost.setEntity(reqEntity);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = httpclient.execute(httppost);
        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
        System.out.println("H5统一下单返回xml：" + strResult);
        return strResult;
    }

    /**
     * 获取h5支付下单返回的参数
     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
     *
     * @param
     * @return
     */
    public static Map<String, Object> getPayH5Map(String prePayInfoXml) {
        Map<String, Object> map = new HashMap<String, Object>();
        String result_code = getXmlPara(prePayInfoXml, "result_code");
        String return_code = getXmlPara(prePayInfoXml, "return_code");
        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code);

        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
            // 统一下单返回xml中prepay_id （预支付交易会话标识）
            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
            String mweb_url = getXmlPara(prePayInfoXml, "mweb_url");
            // 统一下单返回xml中mweb_url （支付跳转链接）,支付成功跳转redirect_url的链接
            //String mweb_url = getXmlPara(prePayInfoXml, "mweb_url") + "&redirect_url=" + URLEncoder.encode(WxPayConstants.paySuccess);
            map.put("result_code", result_code);
            map.put("return_code", return_code);
            map.put("prepay_id", prepay_id);
            map.put("mweb_url", mweb_url);
            System.out.println("H5统一下单返回map：" + map);
            return map;
        }else{
            map.put("result_code", result_code);
            map.put("return_code", return_code);
            return map;

        }
    }

    /**
     * 公众号内支付：统一下单
     *
     * @param
     * @param
     * @param
     * @param
     * @param
     * @return
     * @throws IOException
     */
    public static String UnifiedOrderPublic(String payId, Integer totel_fee, String openId,String appId, String mchId, String body, String key, String ipAddrStr) throws Exception{
        // 设置访问路径
        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // 随机
        String nonce_str = getNonceStr().toUpperCase();
        // 组装请求参数,按照ASCII排序
        String unifiedOrdersign =
                "appid=" +appId+
                "&body=" + body +
                "&mch_id=" + mchId +
                "&nonce_str=" + nonce_str +
                "&notify_url=" + WxPayConstants.NOTIFY_URL +
                "&openid=" + openId +
                "&out_trade_no=" + payId +
                "&spbill_create_ip=" + ipAddrStr +
                "&total_fee=" + totel_fee.toString() +
                "&trade_type=" + WxPayConstants.TRADE_TYPE_JS +
                "&key=" + key;
        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
        System.out.println("统一下单参与签名的字符串是：" + unifiedOrdersign);

        String sign = MD5.calcMD5(unifiedOrdersign).toUpperCase();

        System.out.println("统一下单参与签名值是：" + sign);

        // 组装包含openid用于请求统一下单返回结果的XML
        StringBuilder sb = new StringBuilder("");
        sb.append("<xml>");
        setXmlKV(sb, "appid", appId);
        setXmlKV(sb, "body", body);
        setXmlKV(sb, "mch_id", mchId);
        setXmlKV(sb, "nonce_str", nonce_str);
        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_URL);
        setXmlKV(sb, "openid", openId);
        setXmlKV(sb, "out_trade_no", payId);
        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
        setXmlKV(sb, "total_fee", totel_fee.toString());
        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_JS);
        setXmlKV(sb, "sign", sign);
        sb.append("</xml>");
        System.out.println("统一下单请求：" + sb);
        // 这个处理是为了防止传中文的时候出现签名错误
        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
        httppost.setEntity(reqEntity);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = httpclient.execute(httppost);
        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
        System.out.println("统一下单返回xml：" + strResult);

        return strResult;
    }
    /**
     * 获取公众号支付下单返回的参数
     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
     *
     * @param
     * @return
     */
    public static Map<String,Object> getPayMapPublic(String prePayInfoXml,String appId,String key) {
        Map<String, Object> map = new HashMap<String, Object>();
        String result_code = getXmlPara(prePayInfoXml, "result_code");
        String return_code = getXmlPara(prePayInfoXml, "return_code");

        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code);

        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");// 统一下单返回xml中prepay_id
            String timeStamp = String.valueOf((System.currentTimeMillis() / 1000));// 1970年到现在的秒数
            String nonceStr = getNonceStr().toUpperCase();// 随机数据字符串
            String packageStr = "prepay_id=" + prepay_id;
            String signType = "MD5";

            String paySign1 =
                    "appId=" + appId +
                            "&nonceStr=" + nonceStr +
                            "&package=" + packageStr +
                            "&signType=" + signType +
                            "&timeStamp=" + timeStamp +
                            "&key=" + key;
            // 注意这里的参数要根据ASCII码排序
            System.out.println("getPayMap参与签名的字符串是：" + paySign1);
            String paySign = MD5.calcMD5(paySign1).toUpperCase();

            // 将数据MD5加密
            map.put("result_code", result_code);
            map.put("return_code", return_code);
            map.put("appId", appId);
            map.put("timeStamp", timeStamp);
            map.put("nonceStr", nonceStr);
            map.put("packageStr", packageStr);
            map.put("signType", signType);
            map.put("paySign", paySign);
            map.put("prepay_id", prepay_id);
            System.out.println("公众号下单返回map：" + map);
            return map;

        }else{
            map.put("result_code", result_code);
            map.put("return_code", return_code);
            return map;

        }
    }

    /**
     * 微信APP支付：统一下单
     *
     * @param body
     * @return map
     * @throws IOException
     */
    public static String UnifiedOrderApp(String payId, Integer totel_fee, String APPID, String MCH_ID, String body, String key, String ipAddrStr) throws Exception{
        // 设置访问路径
        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // 随机
        String nonce_str = getNonceStr().toUpperCase();
        // 组装请求参数,按照ASCII排序

        String unifiedOrdersign =
                "appid=" + APPID +
                        "&body=" + body +
                        "&mch_id=" + MCH_ID +
                        "&nonce_str=" + nonce_str +
                        "&notify_url=" + WxPayConstants.NOTIFY_URL +
                        "&out_trade_no=" + payId +
                        "&spbill_create_ip=" + ipAddrStr +
                        "&total_fee=" + totel_fee.toString() +
                        "&trade_type=" + WxPayConstants.TRADE_TYPE_APP +
                        "&key=" + key;
        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
        System.out.println("APP统一下单参与签名的字符串是：" + unifiedOrdersign);
        String sign1 = MD5.calcMD5(unifiedOrdersign).toUpperCase();
        String sign = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, key).toUpperCase();
        System.out.println("APP下单MD5值:" + sign+";APP下单Md5Encrypt值:"+sign1+";APP下单HMACSHA256值:"+sign2);
        // 组装包含openid用于请求统一下单返回结果的XML
        StringBuilder sb = new StringBuilder("");
        sb.append("<xml>");
        setXmlKV(sb, "appid", APPID);
        setXmlKV(sb, "body", body);
        setXmlKV(sb, "mch_id", MCH_ID);
        setXmlKV(sb, "nonce_str", nonce_str);
        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_URL);
        setXmlKV(sb, "out_trade_no", payId);
        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
        setXmlKV(sb, "total_fee", totel_fee.toString());
        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_APP);
        setXmlKV(sb, "sign", sign);
        sb.append("</xml>");
        System.out.println("APP统一下单请求：" + sb);
        // 这个处理是为了防止传中文的时候出现签名错误
        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
        httppost.setEntity(reqEntity);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = httpclient.execute(httppost);
        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
        System.out.println("APP统一下单返回xml：" + strResult);
        return strResult;
    }
    /**
     * 获取APP支付下单返回的参数
     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
     *
     * @param
     * @return
     */
    public static Map<String, Object> getPayAPPMap(String prePayInfoXml) {
        Map<String, Object> map = new HashMap<String, Object>();
        String result_code = getXmlPara(prePayInfoXml, "result_code");
        String return_code = getXmlPara(prePayInfoXml, "return_code");

        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code);

        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
            // 统一下单返回xml中prepay_id （预支付交易会话标识）
            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
            String trade_type = getXmlPara(prePayInfoXml, "trade_type");

            map.put("result_code", result_code);
            map.put("return_code", return_code);
            map.put("prepay_id", prepay_id);
            map.put("trade_type", trade_type);
            System.out.println("APP统一下单返回map：" + map);
            return map;
        } else {
            map.put("result_code", result_code);
            map.put("return_code", return_code);

            return map;
        }

    }

    /***
     * 微信扫二维码支付；统一下单
     * @param payId
     * @param totel_fee
     * @param appId
     * @param mchId
     * @param body
     * @param key
     * @param ipAddrStr
     * @return
     */
    public static String UnifiedOrderScan(String payId, Integer totel_fee, String appId, String mchId, String body, String key, String ipAddrStr) throws Exception {
        // 设置访问路径
        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // 随机
        String nonce_str = getNonceStr().toUpperCase();
        // 组装请求参数,按照ASCII排序

        String unifiedOrdersign =
                "appid=" + appId +
                        "&body=" + body +
                        "&mch_id=" + mchId +
                        "&nonce_str=" + nonce_str +
                        "&notify_url=" + WxPayConstants.NOTIFY_URL +
                        "&out_trade_no=" + payId +
                        "&spbill_create_ip=" + ipAddrStr +
                        "&total_fee=" + totel_fee.toString() +
                        "&trade_type=" + WxPayConstants.TRADE_TYPE_SCAN +
                        "&key=" + key;
        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
        System.out.println("扫二维码支付统一下单参与签名的字符串是：" + unifiedOrdersign);

        String sign1 = MD5.calcMD5(unifiedOrdersign).toUpperCase();
        System.out.println("扫二维码支付统一下单参与签名值是：" + sign1);

        String sign = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
        System.out.println("扫二维码支付统一下单参与签名值是：" + sign);

        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, WxPayConstants.KEY).toUpperCase();
        System.out.println("扫二维码支付统一下单参与签名值是：" + sign2);
        // 组装包含openid用于请求统一下单返回结果的XML
        StringBuilder sb = new StringBuilder("");
        sb.append("<xml>");
        setXmlKV(sb, "appid", appId);
        setXmlKV(sb, "body", body);
        setXmlKV(sb, "mch_id", mchId);
        setXmlKV(sb, "nonce_str", nonce_str);
        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_URL);
        setXmlKV(sb, "out_trade_no", payId);
        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
        setXmlKV(sb, "total_fee", totel_fee.toString());
        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_SCAN);
        setXmlKV(sb, "sign", sign);
        sb.append("</xml>");
        System.out.println("扫二维码支付统一下单请求：" + sb);
        // 这个处理是为了防止传中文的时候出现签名错误
        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
        httppost.setEntity(reqEntity);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = httpclient.execute(httppost);
        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
        System.out.println("扫二维码支付统一下单返回xml：" + strResult);
        return strResult;
    }
    /***
     * 获取扫码支付预下单后，微信回复的prepay_id和trade_type和code_url
     * @param prePayInfoXml
     * @return
     */
    public static Map<String, Object> getPayScanMap(String prePayInfoXml) {
        Map<String, Object> map = new HashMap<String, Object>();
        String result_code = getXmlPara(prePayInfoXml, "result_code");
        String return_code = getXmlPara(prePayInfoXml, "return_code");

        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code );

        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
            // 统一下单返回xml中prepay_id （预支付交易会话标识）
            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
            String trade_type = getXmlPara(prePayInfoXml, "trade_type");
            String code_url=getXmlPara(prePayInfoXml, "code_url");

            map.put("prepay_id", prepay_id);
            map.put("trade_type", trade_type);
            map.put("code_url",code_url);
            map.put("result_code", result_code);
            map.put("return_code", return_code);

            return map;
        } else {
            map.put("result_code", result_code);
            map.put("return_code", return_code);

            return map;
        }
    }

    /***
     * 微信支付结果数据回调处理工具类
     * @param request
     * @return
     */
    public static Map getNotifyResult(HttpServletRequest request) {
        String inputLine;
        String notifyXml = "";
        String resXml = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notifyXml += inputLine;
            }
            request.getReader().close();
        } catch (Exception e) {
            System.out.println("xml获取失败：" + e);
            e.printStackTrace();
        }
        System.out.println("接收到的xml：" + notifyXml);

        String result_code = getXmlPara(notifyXml, "result_code");
        String return_code = getXmlPara(notifyXml, "return_code");

        String appid = getXmlPara(notifyXml, "appid");
        String bank_type = getXmlPara(notifyXml, "bank_type");
        String cash_fee = getXmlPara(notifyXml, "cash_fee");
        String fee_type = getXmlPara(notifyXml, "fee_type");
        String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
        String mch_id = getXmlPara(notifyXml, "mch_id");
        String nonce_str = getXmlPara(notifyXml, "nonce_str");
        String openid = getXmlPara(notifyXml, "openid");
        String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
        String sign = getXmlPara(notifyXml, "sign");
        String time_end = getXmlPara(notifyXml, "time_end");
        String total_fee = getXmlPara(notifyXml, "total_fee");
        String trade_type = getXmlPara(notifyXml, "trade_type");
        String transaction_id = getXmlPara(notifyXml, "transaction_id");

        //返回一个map，map中包含了回复给微信的xml和调用北京接口的参数
        Map<String, Object> returnMap = new HashMap<String, Object>();

        // 本地计算签名与微信返回签名不同||返回结果为不成功
        if ("FAIL".equals(result_code) || "FAIL".equals(return_code)) {
            System.out.println("支付失败！");
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";

            returnMap.put("resXml", resXml);
            returnMap.put("out_trade_no", out_trade_no);
            returnMap.put("total_fee", total_fee);
            returnMap.put("result_code", result_code);
            returnMap.put("return_code", return_code);
            returnMap.put("appid", appid);
            returnMap.put("bank_type", bank_type);
            returnMap.put("cash_fee", cash_fee);
            returnMap.put("fee_type", fee_type);
            returnMap.put("is_subscribe", is_subscribe);
            returnMap.put("mch_id", mch_id);
            returnMap.put("nonce_str", nonce_str);
            returnMap.put("openid", openid);
            returnMap.put("sign", sign);
            returnMap.put("time_end", time_end);
            returnMap.put("trade_type", trade_type);
            returnMap.put("transaction_id", transaction_id);
            return returnMap;
        } else {
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            System.out.println("支付成功，out_trade_no(订单号)为：" + out_trade_no + ";total_fee(金额)为:" + total_fee + ";result_code(回调返回)为:" + result_code);

            returnMap.put("resXml", resXml);
            returnMap.put("out_trade_no", out_trade_no);
            returnMap.put("total_fee", total_fee);
            returnMap.put("result_code", result_code);
            returnMap.put("return_code", return_code);
            returnMap.put("appid", appid);
            returnMap.put("bank_type", bank_type);
            returnMap.put("cash_fee", cash_fee);
            returnMap.put("fee_type", fee_type);
            returnMap.put("is_subscribe", is_subscribe);
            returnMap.put("mch_id", mch_id);
            returnMap.put("nonce_str", nonce_str);
            returnMap.put("openid", openid);
            returnMap.put("sign", sign);
            returnMap.put("time_end", time_end);
            returnMap.put("trade_type", trade_type);
            returnMap.put("transaction_id", transaction_id);
            return returnMap;
        }


    }
}
